#include <QFileInfoList>
#include <QDir>
#include <QDebug>

#include "conexao.h"
#include "tela.h"

Conexao::Conexao(QString endereco_servidor)
{
    this->dados_rede = new QTcpSocket();
    this->dados_rede->connectToHost(endereco_servidor, 20000, QIODevice::ReadWrite);
    connect (this->dados_rede, SIGNAL(connected()), this, SLOT(conexaoEstabelecida()));
    connect (this->dados_rede, SIGNAL(readyRead()), this, SLOT(dadosRecebidos()));
    connect (this->dados_rede, SIGNAL(error(QAbstractSocket::SocketError)),
             this, SIGNAL(erroRede(QAbstractSocket::SocketError)));
    this->visualizador_arquivos = new QTreeWidget();
}

void Conexao::conexaoEstabelecida()
{
    emit this->conexaoIniciada();
    this->enviarListaArquivos();
}

void Conexao::dadosRecebidos()
{
    QByteArray dados = this->dados_rede->readAll();
    this->dados.append(dados);
    if (this->dados.contains("#lista#") && this->dados.contains("#fim#"))
        this->processarLista();
    else if (this->dados.contains("#remover#") && this->dados.contains("#fim#"))
        this->conexaoCaiu();
    else if (this->dados.contains("arquivo") && this->dados.contains("#fim#"))
        this->adicionarArquivoExterno();
}

void Conexao::conexaoCaiu()
{
    QString dados(this->dados);
    this->dados.clear();

    dados.replace("#fim#", "");
    dados.replace("#remover#", "");

    if (dados == "")
        return;

    for (int i = 0; i < this->arquivos_disponiveis.size(); i++)
        qDebug () << this->arquivos_disponiveis.at(i)->getNome() << this->arquivos_disponiveis.at(i)->getLocalizacao();

    for (int j = 0; j < this->arquivos_disponiveis.size(); j++) {
        if (this->arquivos_disponiveis.at(j)->getLocalizacao().contains(dados)) {
            this->arquivos_disponiveis.at(j)->removerLocalizacao(dados);
        }
    }

    for (int i = 0; i < this->arquivos_disponiveis.size(); i++) {
        if (this->arquivos_disponiveis.at(i)->getLocalizacao().size() == 0) {
            this->arquivos_disponiveis.remove(i);
            delete this->visualizador_arquivos->topLevelItem(i);
            i--;
        }
    }

    this->visualizador_arquivos->update();
}

void Conexao::processarLista ()
{
    QString dados(this->dados);

    this->dados.clear();

    dados.replace("#fim#", "");
    dados.replace("#lista#", "");

    if (dados == "")
        return;

    QStringList itens_lista = dados.split("#");

    QList<FileItem*> arquivos_novos;

    for (int i = 0; i < itens_lista.size(); i++) {
        FileItem* item = new FileItem();
        item->setNomeArquivo(itens_lista.at(i).split("|").at(0));
        item->setText(0,item->getNome());
        item->setTamanho(itens_lista.at(i).split("|").at(1).toLongLong());
        for (int j = 2; j < itens_lista.at(i).split("|").size(); j++) {
            item->adicionarLocalizacao(itens_lista.at(i).split("|").at(j));
        }
        arquivos_novos.append(item);
    }

    for (int i = 0; i < arquivos_novos.size(); i++) {
        bool inserted = false;
        int j;
        for (j = 0; j < this->arquivos_disponiveis.size() && !inserted; j++) {
            if (this->arquivos_disponiveis[j]->getNome() == arquivos_novos.at(i)->getNome() &&
                this->arquivos_disponiveis[j]->getTamanho() == arquivos_novos.at(i)->getTamanho()) {
                for (int k = 0; k < arquivos_novos.at(i)->getLocalizacao().size(); k++)
                    this->arquivos_disponiveis[j]->adicionarLocalizacao(arquivos_novos.at(i)->getLocalizacao().at(k));
                inserted = true;
            }
        }
        if (!inserted) {
            this->arquivos_disponiveis.append(arquivos_novos.at(i));
            this->visualizador_arquivos->addTopLevelItem(arquivos_novos.at(i));
        }
    }
    this->visualizador_arquivos->update();

    for (int i = 0; i < this->arquivos_disponiveis.size(); i++)
        qDebug () << this->arquivos_disponiveis.at(i)->getNome() << this->arquivos_disponiveis.at(i)->getLocalizacao();
}

void Conexao::enviarListaArquivos()
{
    QFileInfoList list;
    QDir dir(Tela::pasta_inicial);
    list = dir.entryInfoList(QDir::Files);
    QByteArray dados;
    dados.append(QByteArray("#lista"));
    for (int i = 0; i < list.size(); i++) {

        QString dados_arquivo = "#";
        FileItem* item = new FileItem(this->visualizador_arquivos);
        dados_arquivo.append(list.at(i).fileName() + "|");
        item->setText(0, list.at(i).fileName());
        item->setNomeArquivo(list.at(i).fileName());
        dados_arquivo.append(QString::number(list.at(i).size()) + "|");
        item->setTamanho(list.at(i).size());
        dados_arquivo.append(this->dados_rede->localAddress().toString());
        item->adicionarLocalizacao(this->dados_rede->localAddress().toString());
        dados.append(dados_arquivo);
        this->arquivos_disponiveis.append(item);
    }
    dados.append("#fim#");
    this->dados_rede->write(dados);
}

void Conexao::adicionarArquivoInterno(FileItem *item)
{
    bool inserted = false;

    qDebug () << item->getNome() << item->getLocalizacao();

    for (int i = 0; i < this->arquivos_disponiveis.size() && !inserted; i++) {
        if (this->arquivos_disponiveis.at(i)->getNome() == item->getNome() &&
            this->arquivos_disponiveis.at(i)->getTamanho() == item->getTamanho()) {
            this->arquivos_disponiveis.at(i)->adicionarLocalizacao(item->getLocalizacao().at(0));
            inserted = true;
        }
    }

    if (!inserted) {
        this->arquivos_disponiveis.append(item);
        this->visualizador_arquivos->addTopLevelItem(item);
        this->visualizador_arquivos->update();
    }

    QString dados = "#arquivo#" + item->getNome() + "|" +
                    QString::number(item->getTamanho()) + "|" +
                    item->getLocalizacao().at(0) + "#fim#";

    this->dados_rede->write(QByteArray().append(dados));
}

void Conexao::adicionarArquivoExterno()
{
    QString dados(this->dados);

    this->dados.clear();

    dados.replace("#fim#", "");
    dados.replace("#arquivo#", "");

    if (dados == "")
        return;

    QStringList dados_arquivo = dados.split("|");

    if (dados_arquivo.size() != 3)
        return;

    FileItem* item = new FileItem();
    item->setNomeArquivo(dados_arquivo.at(0));
    item->setTamanho(dados_arquivo.at(1).toLongLong());
    item->adicionarLocalizacao(dados_arquivo.at(2));

    bool inserted = false;

    for (int i = 0; i < this->arquivos_disponiveis.size() && !inserted; i++) {
        if (this->arquivos_disponiveis.at(i)->getNome() == item->getNome() &&
            this->arquivos_disponiveis.at(i)->getTamanho() == item->getTamanho()) {
            this->arquivos_disponiveis.at(i)->adicionarLocalizacao(item->getLocalizacao().at(0));
            inserted = true;
        }
    }

    if (!inserted) {
        this->arquivos_disponiveis.append(item);
        this->visualizador_arquivos->addTopLevelItem(item);
        this->visualizador_arquivos->update();
    }

    this->visualizador_arquivos->update();
}
